﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace OnlineScheduling.DomainModel
{
    public class Processor : IComparable, IComparable<Processor>, ICloneable
    {
        public int Id { get; private set; }
        public Task CurrentTask { get; private set; }
        public ProcessorsPriorityType ProcessorsPriorityType { get;  set; }
        public int TimeOfPreemptingCurrentTask { get; set; }

        public bool IsBusy
        {
            get
            {
                return CurrentTask != null;
            }
        }

        public Processor(int id, ProcessorsPriorityType processorsPriorityType)
        {
            Id = id;
            CurrentTask = null;
            ProcessorsPriorityType = processorsPriorityType;
            TimeOfPreemptingCurrentTask = -1;

        }

        public void AssignTask(Task task, int time)
        {
            CurrentTask = task;
            CurrentTask.ResumeOrStart(time,Id);
            TimeOfPreemptingCurrentTask = time + task.Duration;
        }

        public void RoundRobinAssignTask(Task task, int time, int timeQuant)
        {
            CurrentTask = task;
            CurrentTask.ResumeOrStart(time, Id);
            TimeOfPreemptingCurrentTask = time + timeQuant; 
        }

        public Task StopProcessingTask(int time)
        {
            if (!IsBusy) return null;
            
            CurrentTask.StopProceeding(time);
            Task toReturn= CurrentTask;
            CurrentTask= null;
            TimeOfPreemptingCurrentTask = -1;
            return toReturn;

        }

        #region IComparable<Processor> Members

        public int CompareTo(object otherCPU)
        {
            int result = 0;
            Processor other = otherCPU as Processor;
            switch (ProcessorsPriorityType)
            {
                case ProcessorsPriorityType.ByEarliestFinish:
                    if (CurrentTask == null) result = -1;
                    else if (other.CurrentTask == null) result = 1;
                    else if (CurrentTask.ExpectedTimeToBeDone < other.CurrentTask.ExpectedTimeToBeDone) result = 1;
                    else if (CurrentTask.ExpectedTimeToBeDone == other.CurrentTask.ExpectedTimeToBeDone) result = 0;
                    else result = -1;
                    break;
                case ProcessorsPriorityType.ByWSRTMinFactor:
                    if (CurrentTask == null) result = -1;
                    else if (other.CurrentTask == null) result = 1;
                    else if (CurrentTask.PriorityValue > other.CurrentTask.PriorityValue) result = -1;
                    else if (CurrentTask.PriorityValue == other.CurrentTask.PriorityValue) result = 0;
                    else result = 1;
                    break;
            }

            return result;
        }

        #endregion

      

        #region IComparable<Processor> Members

        public int CompareTo(Processor other)
        {
            int result = 0;
            switch (ProcessorsPriorityType)
            {
                case ProcessorsPriorityType.ByEarliestFinish:
                    if (CurrentTask == null) result = -1;
                    else if (other.CurrentTask == null) result = 1;
                    else if (CurrentTask.ExpectedTimeToBeDone < other.CurrentTask.ExpectedTimeToBeDone) result = 1;
                    else if (CurrentTask.ExpectedTimeToBeDone == other.CurrentTask.ExpectedTimeToBeDone) result = 0;
                    else result = -1;
                    break;
                case ProcessorsPriorityType.ByWSRTMinFactor:
                    if (CurrentTask == null) result = -1;
                    else if (other.CurrentTask == null) result = 1;
                    else if (CurrentTask.PriorityValue > other.CurrentTask.PriorityValue) result = -1;
                    else if (CurrentTask.PriorityValue == other.CurrentTask.PriorityValue) result = 0;
                    else result = 1;
                    break;
            }

            return result;
        }

        #endregion

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof (Processor)) return false;
            return Equals((Processor) obj);
        }

        public bool Equals(Processor other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return other.Id == Id;
        }

        public override int GetHashCode()
        {
            return Id;
        }

        public static bool operator ==(Processor left, Processor right)
        {
            return Equals(left, right);
        }

        public static bool operator !=(Processor left, Processor right)
        {
            return !Equals(left, right);
        }


        #region ICloneable Members

        public object Clone()
        {
            return new Processor(Id, ProcessorsPriorityType); 
        }

        #endregion
    }

    
}
